#pragma once

#include <iostream>
#include <time.h>
#include <map>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;

enum // 可以设置日志等级
{
    Debug,
    Info,
    Warning,
    Error,
    Fatal
};
enum // 打印方式
{
    Screen,
    onlyfile,
    classifyfile
};
const string logdir = "log"; // 目录文件
class Log
{
public:
    Log()
    {
        levermap[Debug] = "Debug";
        levermap[Info] = "Info";
        levermap[Warning] = "Warning";
        levermap[Error] = "Error";
        levermap[Fatal] = "Fatal";

        mkdir(logdir.c_str(), 0777); // 创建目录，并在指定目录下打印
    }
    void exchange(string &s, tm *&cur_time) // 时间戳转换成标准时间
    {
        s = to_string(cur_time->tm_year + 1900) + '/' + to_string(cur_time->tm_mon) + '/' + to_string(cur_time->tm_mday) + '-' + to_string(cur_time->tm_hour) + ':' + to_string(cur_time->tm_min) + ':' + to_string(cur_time->tm_sec);
    }
    void write_way(const string &filename, const string &loginfo) // 文件打印
    {
        int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
        if (fd == -1)
            cout << "文件打开失败" << endl;
        write(fd, loginfo.c_str(), loginfo.size());
        close(fd);
    }
    void write_log(int lever, const string &loginfo) // 日志写入位置
    {
        string tmp = logdir + '/' + "log.";
        switch (style)
        {
        case 0: // 显示器打印
            cout << loginfo;
            break;
        case 1: // log.txt里打印
            write_way(tmp + "txt", loginfo);
            break;
        case 2: // 分类到各自对应的文件里打印
            write_way(tmp + levermap[lever], loginfo);
            break;
        default:
            break;
        }
    }
    void enable(int sty)
    {
        style = sty;
    }
    void Log_infom(int lever, const char *format, ...) // 格式formats
    {
        char tmp[1024];
        va_list args;                              // 可变参数部分的起始地址
        va_start(args, format);                    // 初始化，通过format确定可变参数个数
        vsnprintf(tmp, sizeof(tmp), format, args); // 将数据写到tmp中
        va_end(args);                              //

        time_t t = time(nullptr);     // 得到当前的时间戳
        tm *cur_time = localtime(&t); // 传入时间戳
        string s;
        exchange(s, cur_time); // 转换成具体的时间
        string loginfo;
        loginfo = loginfo + tmp + ' ' + '[' + levermap[lever] + ']' + '[' + s + ']' + '\n';

        write_log(lever, loginfo);
    }

    ~Log()
    {
    }

private:
    map<int, string> levermap;
    int style = 0; // 默认往显示器中打印
    int lever = Debug;
};
Log lg;
